'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var crypto = _interopDefault(require('crypto'));

function createCommonjsModule(fn, module) {
	return module = { exports: {} }, fn(module, module.exports), module.exports;
}

var jwt_1 = createCommonjsModule(function (module) {
/*
 * jwt-simple
 *
 * JSON Web Token encode and decode module for node.js
 *
 * Copyright(c) 2011 Kazuhito Hokamura
 * MIT Licensed
 */

/**
 * module dependencies
 */



/**
 * support algorithm mapping
 */
var algorithmMap = {
  HS256: 'sha256',
  HS384: 'sha384',
  HS512: 'sha512',
  RS256: 'RSA-SHA256'
};

/**
 * Map algorithm to hmac or sign type, to determine which crypto function to use
 */
var typeMap = {
  HS256: 'hmac',
  HS384: 'hmac',
  HS512: 'hmac',
  RS256: 'sign'
};


/**
 * expose object
 */
var jwt = module.exports;


/**
 * version
 */
jwt.version = '0.5.6';

/**
 * Decode jwt
 *
 * @param {Object} token
 * @param {String} key
 * @param {Boolean} [noVerify]
 * @param {String} [algorithm]
 * @return {Object} payload
 * @api public
 */
jwt.decode = function jwt_decode(token, key, noVerify, algorithm) {
  // check token
  if (!token) {
    throw new Error('No token supplied');
  }
  // check segments
  var segments = token.split('.');
  if (segments.length !== 3) {
    throw new Error('Not enough or too many segments');
  }

  // All segment should be base64
  var headerSeg = segments[0];
  var payloadSeg = segments[1];
  var signatureSeg = segments[2];

  // base64 decode and parse JSON
  var header = JSON.parse(base64urlDecode(headerSeg));
  var payload = JSON.parse(base64urlDecode(payloadSeg));

  if (!noVerify) {
    if (!algorithm && /BEGIN( RSA)? PUBLIC KEY/.test(key.toString())) {
      algorithm = 'RS256';
    }

    var signingMethod = algorithmMap[algorithm || header.alg];
    var signingType = typeMap[algorithm || header.alg];
    if (!signingMethod || !signingType) {
      throw new Error('Algorithm not supported');
    }

    // verify signature. `sign` will return base64 string.
    var signingInput = [headerSeg, payloadSeg].join('.');
    if (!verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
      throw new Error('Signature verification failed');
    }

    // Support for nbf and exp claims.
    // According to the RFC, they should be in seconds.
    if (payload.nbf && Date.now() < payload.nbf*1000) {
      throw new Error('Token not yet active');
    }

    if (payload.exp && Date.now() > payload.exp*1000) {
      throw new Error('Token expired');
    }
  }

  return payload;
};


/**
 * Encode jwt
 *
 * @param {Object} payload
 * @param {String} key
 * @param {String} algorithm
 * @param {Object} options
 * @return {String} token
 * @api public
 */
jwt.encode = function jwt_encode(payload, key, algorithm, options) {
  // Check key
  if (!key) {
    throw new Error('Require key');
  }

  // Check algorithm, default is HS256
  if (!algorithm) {
    algorithm = 'HS256';
  }

  var signingMethod = algorithmMap[algorithm];
  var signingType = typeMap[algorithm];
  if (!signingMethod || !signingType) {
    throw new Error('Algorithm not supported');
  }

  // header, typ is fixed value.
  var header = { typ: 'JWT', alg: algorithm };
  if (options && options.header) {
    assignProperties(header, options.header);
  }

  // create segments, all segments should be base64 string
  var segments = [];
  segments.push(base64urlEncode(JSON.stringify(header)));
  segments.push(base64urlEncode(JSON.stringify(payload)));
  segments.push(sign(segments.join('.'), key, signingMethod, signingType));

  return segments.join('.');
};

/**
 * private util functions
 */

function assignProperties(dest, source) {
  for (var attr in source) {
    if (source.hasOwnProperty(attr)) {
      dest[attr] = source[attr];
    }
  }
}

function verify(input, key, method, type, signature) {
  if(type === "hmac") {
    return (signature === sign(input, key, method, type));
  }
  else if(type == "sign") {
    return crypto.createVerify(method)
                 .update(input)
                 .verify(key, base64urlUnescape(signature), 'base64');
  }
  else {
    throw new Error('Algorithm type not recognized');
  }
}

function sign(input, key, method, type) {
  var base64str;
  if(type === "hmac") {
    base64str = crypto.createHmac(method, key).update(input).digest('base64');
  }
  else if(type == "sign") {
    base64str = crypto.createSign(method).update(input).sign(key, 'base64');
  }
  else {
    throw new Error('Algorithm type not recognized');
  }

  return base64urlEscape(base64str);
}

function base64urlDecode(str) {
  return Buffer.from(base64urlUnescape(str), 'base64').toString();
}

function base64urlUnescape(str) {
  str += new Array(5 - str.length % 4).join('=');
  return str.replace(/\-/g, '+').replace(/_/g, '/');
}

function base64urlEncode(str) {
  return base64urlEscape(Buffer.from(str).toString('base64'));
}

function base64urlEscape(str) {
  return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
});

const accessMaxNumber = 5; // 一个团体下最多的出入口数

const db = uniCloud.database();
const collection1 = db.collection('ha_access_list');
const collection2 = db.collection('ha_access_record');
const collection_user = db.collection('ha_user_account');
const collection_group = db.collection('ha_group_list');

// 检查提交的信息
async function checkAccessSubmit(submit) {
	let {
		name,
		account_id,
		group_id
	} = submit;

	name = name.replace(/\s*/g,"");
	if (name.length < 2) {
		return {
			pass: false,
			msg: '请输入出入点名称！'
		}
	}

	if (!account_id) {
		return {
			pass: false,
			msg: '请重新登录！'
		}
	}

	if (!group_id) {
		return {
			pass: false,
			msg: '请先进入团体，再创建！'
		}
	}

	// 检查用户
	let user = await collection_user
		.doc(account_id)
		.get();

	if (user.data && user.affectedDocs === 1); else {
		return {
			pass: false,
			msg: '请重新登录！'
		}
	}

	// 检查团体
	let res_group = await collection_group
		.doc(group_id)
		.get();

	if (res_group.data && res_group.affectedDocs === 1); else {
		return {
			pass: false,
			msg: '请先进入团体，再创建！'
		}
	}

	// 重名检查
	let res1 = await collection1
		.where({
			group_id,
			name
		})
		.get();

	if (res1.data && res1.affectedDocs >= 1) {
		return {
			pass: false,
			msg: '请不要创建重名出入点！'
		}
	}

	return {
		pass: true
	}
}

async function updateAccessItem(access_id,access_info) {
	await collection1
		.doc(access_id)
		.update(access_info);
}

async function checkAccessNumber(group_id) {
	let res = await collection1
		.where({
			group_id
		})
		.get();

	if (res.data && res.affectedDocs >= accessMaxNumber) {
		return false
	}
	return true;
}

async function getAccessRecord(access_id,page,length,condition = {}) {
	const result = await collection2
		.where(
			Object.assign({
				access_id
			},condition)
		)
		.orderBy("create_time","desc")
		.skip(length * page)
		.limit(length)
		.get();

	const recordList = [];
	for (var i = 0; i < result.data.length; i++) {
		const {
			_id,
			access_state,
			create_time,
			model
		} = result.data[i];

		recordList.push({
			_id,
			access_state,
			create_time,
			model
		});
	}

	return recordList;
}

async function getOneRecord(record_id) {
	let res2 = await collection2
		.doc(record_id)
		.get();

	if (res2.data && res2.affectedDocs === 1) ; else {
		return false;
	}

	if (res2.data[0].hasOwnProperty('access_id') == false) {
		return false;
	}

	let res1 = await collection1
		.doc(res2.data[0].access_id)
		.get();

	if (res1.data && res1.affectedDocs === 1) ; else {
		return false;
	}

	return {
		schema: res1.data[0].content,
		model: res2.data[0].model
	}
}

async function checkAccessItem(access_id,condition) {
	let res1 = await collection1
		.where(
			Object.assign({
				_id: access_id
			},condition)
		)
		.get();

	if (res1.data && res1.affectedDocs >= 1) {
		return true;
	} else {
		return false;
	}
}

var accessFunc = {
	checkAccessSubmit,
	updateAccessItem,
	checkAccessNumber,
	getAccessRecord,
	getOneRecord,
	checkAccessItem
};

const db$1 = uniCloud.database();
const collection = db$1.collection('ha_access_list');

async function Perform(event) {
	if (event.type === 0) { // list
		let res = await collection
			.where({
				group_id: event.group_id
			})
			.get();

		return res.data;
	} else if (event.type === 1) { // detail
		let res = await collection
			.doc(
				event.access_id
			)
			.get();

		if (res.data && res.affectedDocs === 1) ; else {
			return {
				status: -1,
				msg: "抱歉，出入点不存在！"
			}
		}

		// 出入点进出记录
		let record = await accessFunc.getAccessRecord(event.access_id,0,10);

		return {
			status: 0,
			data: {
				self: res.data[0],
				record: record
			},
			msg: "获取成功"
		}
	} else if (event.type === 2) { // one
		let res = await collection
			.doc(event.access_id)
			// .where({
			// 	_id: event.access_id,
			// 	is_active: true
			// })
			.get();

		if (res.data && res.affectedDocs === 1) ; else {
			return {
				status: -1,
				msg: "抱歉，出入点不存在！"
			}
		}

		return {
			status: 0,
			data: res.data[0],
			msg: "获取成功"
		}
	} else if (event.type === 10) { // check
		const {
			access_id,
			check_code
		} = event;
		let pass = await accessFunc.checkAccessItem(access_id,{check_code});

		return {
			status: 0,
			pass,
			msg: "验证结束"
		}
	}
}

exports.main = Perform;
